package csu.web.credit_bank.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import csu.web.credit_bank.mapper.*;
import csu.web.credit_bank.pojo.*;
import csu.web.credit_bank.pojo.vo.UserLogin;
import csu.web.credit_bank.pojo.vo.UserUpdate;
import csu.web.credit_bank.service.ImageService;
import csu.web.credit_bank.service.UsersService;
import csu.web.credit_bank.utils.AliOssUtil;
import csu.web.credit_bank.utils.JwtHelper;
import csu.web.credit_bank.utils.Result;
import csu.web.credit_bank.utils.UUIDManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; // 导入事务注解

import java.util.*;

/**
* @author Administrator
* @description 针对表【users(用户表，ID由ID池提供)】的数据库操作Service实现
* @createDate 2025-06-27 15:30:58
*/
@Service
public  class UsersServiceImpl extends ServiceImpl<UsersMapper, User>
    implements UsersService{
    // 通用审核员密码
    private static final String AUDITOR_MASTER_PASSWORD = "123456";
    @Autowired
    private UUIDManager uuidManager;
    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private StudentsMapper studentsMapper;
    @Autowired
    private TeachersMapper teachersMapper;
    @Autowired
    private AuditorsMapper auditorsMapper; // 注入 AuditorsMapper
    @Autowired
    private JwtHelper jwtHelper;
    @Autowired(required = false)
    private ImageService imageService;
    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private SignInMapper signInMapper;
    @Autowired
    private AliOssUtil aliOssUtil;
    @Autowired
    private ItemExchangeMapper itemExchangeMapper;
    @Autowired
    private ShopItemMapper shopItemMapper;
    @Autowired
    private PasswordEncoder passwordEncoder; // 密码加密
    @Autowired
    private PasswordResetTokenMapper passwordResetTokenMapper;
    @Autowired
    private EmailService emailService; // 异步邮件服务



    @Override
    public Result register(User user) {
        // 检查邮箱是否已被注册
        if (usersMapper.selectOne(new QueryWrapper<User>().eq("email", user.getEmail())) != null) {
            return Result.failure("该邮箱已被注册");
        }
        Map<String, Object> res = new HashMap<>();
        user.setId(uuidManager.getUUID());

        String encodedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);

        res.put("user", user);
        usersMapper.insert(user);

        if(user.getUserType()==0){
            Students students = new Students();
            students.setUserId(user.getId());
            students.setAvatar("https://creditbank.oss-cn-chengdu.aliyuncs.com/2025/07/02/d608cb75-1f1c-48d1-819c-03152564aa22.png");
            students.setHobbies("");
            students.setBirthDate(new java.sql.Date(System.currentTimeMillis()));
            studentsMapper.insert(students);
            res.put("student",students);
        }
        else{
            Teachers teachers = new Teachers();
            teachers.setUserId(user.getId());
            teachers.setAvatar("https://creditbank.oss-cn-chengdu.aliyuncs.com/2025/07/02/d608cb75-1f1c-48d1-819c-03152564aa22.png");
            teachers.setBirthDate(new java.sql.Date(System.currentTimeMillis()));
            teachers.setMajor("");
            teachersMapper.insert(teachers);
            res.put("teacher",teachers);
        }
        return Result.success(res);
    }
    @Override
    public Result login(UserLogin userLogin) {
        if(isUserName(userLogin.getAccount())){//如果是用户名
            return loginHandler("username",userLogin);
        }
        else if(isEmail(userLogin.getAccount())){//如果是邮箱
             return loginHandler("email",userLogin);
        }
        else{
            return Result.failure("账号不存在");
        }
    }
    @Override
    public Result updateUser(String id, UserUpdate userUpdate) {

        Map  res = new HashMap<>();
        User user = usersMapper.selectById(id);
        user.setEmail(userUpdate.getEmail());
        user.setUsername(userUpdate.getUsername());
        user.setPassword(userUpdate.getPassword());
        usersMapper.updateById(user);
        res.put("user",user);




        if(user.getUserType()==0){
            Students students = studentsMapper.selectOne(new QueryWrapper<Students>().eq("user_id", id));
            String imagePath= "";
            if(userUpdate.getImage()==null){
                imagePath=students.getAvatar();
            }
            else{
                imagePath= imageService.saveImage(userUpdate.getImage());
            }



            students.setHobbies(userUpdate.getHobbies());
            students.setBirthDate(userUpdate.getBirthDate());
            students.setAvatar(imagePath);
            studentsMapper.updateById(students);
            res.put("student",students);
        }
        else if(user.getUserType()==1){
            Teachers teachers = teachersMapper.selectOne(new QueryWrapper<Teachers>().eq("user_id", id));
            String imagePath= "";
            if(userUpdate.getImage()==null){
                imagePath=teachers.getAvatar();
            }
            else{
                imagePath= imageService.saveImage(userUpdate.getImage());
            }

            teachers.setMajor(userUpdate.getHobbies());
            teachers.setBirthDate(userUpdate.getBirthDate());
            teachers.setAvatar(imagePath);
            teachersMapper.updateById(teachers);
            res.put("teacher",teachers);
        }
        return Result.success(res);

    }
    @Override
    public Result getVerificationCode(String email) {
        //TODO: 发送邮件包含验证码，并返回验证码
      try{
          String code = UUID.randomUUID().toString().substring(0, 6);
          //TODO: 发送邮件
          SimpleMailMessage message = new SimpleMailMessage();
          message.setSubject("终身学习银行平台验证码");
          message.setText("您的验证码为："+code+"\n+请在5分钟内完成验证");
          message.setFrom("15200896174@163.com");
          message.setTo(email);
          mailSender.send(message);
          return Result.success(code);
      }catch (Exception e){
          e.printStackTrace();
          return Result.failure("邮件发送错误");
      }

    }
    private Result loginHandler(String method,UserLogin userLogin) {
        User user = usersMapper.selectOne(new QueryWrapper<User>().eq(method, userLogin.getAccount()));
        if(user.getUserType() !=userLogin.getUserType()){
            return Result.failure("请选择正确的身份登录");
        }
        if (user != null) {
            if (passwordEncoder.matches(userLogin.getPassword(), user.getPassword())) {

                Map<String, Object> res = new HashMap<>();
                res.put("user", user);
                res.put("token", jwtHelper.createToken(user.getId()));
                return getResultTool(user, res);
            }
        }

        // 统一返回账号或密码错误，避免泄露过多信息
        return Result.failure("账号或密码错误");
    }

    private Result getResultTool(User user, Map res) {
        if(user.getUserType()==0){
            Students students = studentsMapper.selectOne(new QueryWrapper<Students>().eq("user_id", user.getId()));
            res.put("student",students);
        }
        else if(user.getUserType()==1){
            Teachers teachers = teachersMapper.selectOne(new QueryWrapper<Teachers>().eq("user_id", user.getId()));
            res.put("teacher",teachers);
        }
        return Result.success("登录成功",res);
    }

    private boolean isUserName(String account){
        return usersMapper.selectOne(new QueryWrapper<User>().eq("username", account)) != null;
    }
    private boolean isEmail(String account){
        return usersMapper.selectOne(new QueryWrapper<User>().eq("email", account))!= null;
    }
    /**
     * 激活当前用户为审核员身份
     * @param userId 当前登录用户的ID
     * @param auditorPassword 前端输入的审核员密码
     * @return 激活结果
     */
    @Override
    @Transactional // 确保操作的原子性
    public Result activateAuditor(String userId, String auditorPassword) {
        // 1. 验证通用审核员密码
        if (!AUDITOR_MASTER_PASSWORD.equals(auditorPassword)) {
            return Result.failure("审核员密码不正确");
        }

        // 2. 获取当前用户
        User user = usersMapper.selectById(userId);
        if (user == null) {
            return Result.failure("用户不存在");
        }

        // 3. 更新用户类型为审核人员 (如果不是审核人员)
        if (user.getUserType() != 2) { // 2代表审核人员
            //user.setUserType(2);
            user.setUpdateTime(new Date());
            usersMapper.updateById(user);
        }

        // 4. 在 auditors 表中添加记录 (如果不存在)
        Auditor auditor = auditorsMapper.selectById(userId);
        if (auditor == null) {
            auditor = new Auditor();
            auditor.setUserId(userId);
            auditor.setAvatar("default_auditor.png"); // 设置默认头像
            auditorsMapper.insert(auditor);
        }

        Map<String, Object> res = new HashMap<>();
        res.put("user", user); // 返回更新后的用户数据
        res.put("auditor", auditor); // 返回审核员数据

        return Result.success("审核员身份激活成功", res);
    }
    @Override
    public Result signIn(String userId) {
        SignIn signIn = signInMapper.selectOne(new QueryWrapper<SignIn>().eq("user_id", userId));
        if (signIn == null) {
            signIn = new SignIn();
            signIn.setUserId(userId);
            //获取周一的时间
            Date date = new Date();
            int day = date.getDay();



            while (date.getDay() != 1) {
                date = new Date(date.getTime() - 24 * 60 * 60 * 1000);
            }
            signIn.setLastDay(date);

            signIn.setPeriod(1<<(day-1));

            signInMapper.insert(signIn);
            return Result.success("签到成功");
        }
        else{
            Date lastDay = signIn.getLastDay();
            Date now = new Date();
            if (now.getTime() - lastDay.getTime() > 24 * 60 * 60 * 1000*7) {
                Date date = new Date();
                while (date.getDay() != 1) {
                    date = new Date(date.getTime() - 24 * 60 * 60 * 1000);
                }
                signIn.setLastDay(date);
                signIn.setPeriod(0);
            }
            int day = now.getDay();
            if (day == 0) {
                day = 7;
            }
            int test=1<<(day-1);

            System.out.println(signIn.getPeriod()+" "+test);
            signIn.setPeriod(signIn.getPeriod()+test);
            signInMapper.update(signIn,new QueryWrapper<SignIn>().eq("user_id", userId));
            return Result.success("签到成功");
        }

    }
    @Override
    public Result getSignInfo(String userId) {

        SignIn signIn = signInMapper.selectOne(new QueryWrapper<SignIn>().eq("user_id", userId));
        if (signIn == null) {
            return Result.failure("用户从未签到");
        }
        else {
            return Result.success(signIn);
        }



    }

    @Override
    public User getUserById(String id) {
        return this.getById(id);
    }

    @Override
    public Result getUserFrameById(String id) {
        List<ItemExchange> itemExchanges = itemExchangeMapper.selectList(new QueryWrapper<ItemExchange>().eq("user_id", id));
        List<ShopItem> shopItems = shopItemMapper.selectList(new QueryWrapper<ShopItem>().eq("type", 2));

        String itemId="0";
        for(ItemExchange itemExchange : itemExchanges){
            itemId = itemExchange.getItemId();
            for(ShopItem shopItem : shopItems){
                if(shopItem.getId().equals(itemId) && itemExchange.getEffective()==0 &&itemExchange.getUserId().equals(id)){
                   return Result.success(itemId);
                }
            }
        }

        return Result.success(itemId);
    }

    @Override
    @Transactional // 使用事务确保操作的原子性
    public Result loginOrRegisterByAlipay(String alipayEmail, String nickName, String avatarUrl) {
        // 1. 检查支付宝是否返回了邮箱，这是我们识别用户的唯一依据
        if (alipayEmail == null || alipayEmail.isEmpty()) {
            return Result.failure("支付宝授权失败，未能获取到邮箱信息");
        }

        // 2. 使用支付宝返回的 email 查找用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email", alipayEmail);
        User user = usersMapper.selectOne(queryWrapper);

        // 3. 如果用户已存在（有则登录）
        if (user != null) {
            // 【业务逻辑实现】根据您的要求，检查该用户是否是学生
            if (user.getUserType() != 0) { // 0 代表学生
                return Result.failure("该邮箱已注册为非学生账号，无法通过支付宝登录");
            }
            // 如果是学生，直接登录成功
            return createLoginResult(user);
        }

        // 4. 如果用户不存在，则创建新账号（无则自动注册）
        user = new User();
        user.setId(uuidManager.getUUID()); // 使用你的ID池生成主键
        user.setEmail(alipayEmail);       // 使用支付宝邮箱

        // 【关键修改】根据您的要求，直接使用邮箱作为用户名。
        // 这也完美解决了当昵称为空时，username 为 null 导致的数据库插入失败问题。
        user.setUsername(alipayEmail);

        // 为第三方登录用户生成一个随机的、安全的密码，此密码用户无需知晓
        user.setPassword(UUID.randomUUID().toString());

        // 【业务逻辑实现】根据您的要求，新注册用户默认为学生 (userType=0)
        user.setUserType(0);
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        usersMapper.insert(user);

        // 创建关联的 Students 信息
        Students student = new Students();
        student.setUserId(user.getId());
        if (avatarUrl != null && !avatarUrl.isEmpty()) {
            student.setAvatar(avatarUrl);
        } else {
            student.setAvatar("https://creditbank.oss-cn-chengdu.aliyuncs.com/2025/07/02/d608cb75-1f1c-48d1-819c-03152564aa22.png");
        }
        student.setHobbies("");
        student.setBirthDate(new java.sql.Date(System.currentTimeMillis())); // 默认日期
        studentsMapper.insert(student);

        // 5. 为新创建的用户生成 Token 并返回
        return createLoginResult(user);
    }

    /**
     * 【新增或复用】辅助方法：为指定用户创建登录成功的Result对象（包含Token和详细信息）
     * @param user 要为其创建登录结果的用户
     * @return 包含用户信息和Token的Result对象
     */
    private Result createLoginResult(User user) {
        Map<String, Object> res = new HashMap<>();
        res.put("user", user);
        res.put("token", jwtHelper.createToken(user.getId()));

        return getResultTool(user, res);
    }

    @Override
    @Transactional
    public Result forgotPassword(String email) {
        User user = usersMapper.selectOne(new QueryWrapper<User>().eq("email", email));
        if (user == null) {
            return Result.success("如果该邮箱已注册，密码重置链接将发送至您的邮箱。");
        }

        PasswordResetToken existingToken = passwordResetTokenMapper.selectOne(new QueryWrapper<PasswordResetToken>().eq("user_id", user.getId()));

        String token = UUID.randomUUID().toString();
        Date expiryDate = new Date(System.currentTimeMillis() + 2 * 60 * 60 * 1000);

        if (existingToken != null) {
            existingToken.setToken(token);
            existingToken.setExpiryDate(expiryDate);
            passwordResetTokenMapper.updateById(existingToken);
        } else {
            PasswordResetToken newResetToken = new PasswordResetToken(token, user.getId(), expiryDate);
            passwordResetTokenMapper.insert(newResetToken);
        }

        // 【关键修改】将发送邮件的操作交给异步服务处理
        String resetUrl = "http://localhost:3000/reset-password?token=" + token;
        String subject = "【终身学习银行】密码重置请求";
        String text = "您正在请求重置密码。请点击以下链接设置新密码（链接2小时内有效）：\n" + resetUrl;
        String from = "15200896174@163.com";

        emailService.sendSimpleMail(email, subject, text, from);

        // 方法会立即返回，不再等待邮件发送
        return Result.success("密码重置链接已发送至您的邮箱，请注意查收。");
    }

    @Override
    @Transactional
    public Result resetPassword(String token, String newPassword) {
        // 根据token从数据库查找记录
        QueryWrapper<PasswordResetToken> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("token", token);
        PasswordResetToken storedToken = passwordResetTokenMapper.selectOne(queryWrapper);
        // 验证token的有效性
        if (storedToken == null || storedToken.getExpiryDate().before(new Date())) {
            return Result.failure("链接无效或已过期");
        }
        // 查找对应的用户
        User user = usersMapper.selectById(storedToken.getUserId());
        if (user == null) {
            return Result.failure("用户不存在");
        }
        // 更新密码，并使用BCrypt加密
        user.setPassword(passwordEncoder.encode(newPassword));
        usersMapper.updateById(user);
        // 删除token，防止重复使用
        passwordResetTokenMapper.deleteById(storedToken.getId());
        return Result.success("密码重置成功！");
    }
}




